#!/usr/bin/env python
# coding:utf-8
import sys
import os
import time
import json
import MySQLdb
import logging
import comm.common_tools as commtools


def str_dict_utf8(dict_obj):
	return json.dumps(dict_obj).decode('unicode-escape')


def pretty_dict(obj, indent=' '):
	def _pretty(obj, indent):
		for i, tup in enumerate(obj.items()):
			k, v = tup

			# 如果是字符串则拼上""
			if isinstance(k, basestring): k = '"%s"' % k
			if isinstance(v, basestring): v = '"%s"' % v

			# 如果是字典则递归

			if isinstance(v, dict):
				v = ''.join(_pretty(v, indent + ' ' * len(str(k) + ': {')))  # 计算下一层的indent

			# case,根据(k,v)对在哪个位置确定拼接什么
			if i == 0:  # 开头,拼左花括号
				if len(obj) == 1:
					yield '{%s: %s}' % (k, v)
				else:
					yield '{%s: %s,\n' % (k, v)
			elif i == len(obj) - 1:  # 结尾,拼右花括号
				yield '%s%s: %s}' % (indent, k, v)
			else:  # 中间
				yield '%s%s: %s,\n' % (indent, k, v)

	print ''.join(_pretty(obj, indent))


def init_log(filename):
	LOG_FORMAT = "%(asctime)s - %(levelname)s - %(message)s"
	DATE_FORMAT = "%Y%m%d %H:%M:%S"
	filename = filename+'.log'
	logging.basicConfig(filename=filename, level=logging.INFO, format=LOG_FORMAT, datefmt=DATE_FORMAT)
	logging.info('\n\n')
	logging.info('========STARTUP pid=[%d] cmd=%s ========' % (os.getpid(), sys.argv))

# 读取mysql的配置文件
def get_mysql_config():
	conf = {}
	conf['ip']      = '192.168.4.104'
	conf['port']    = '3306'
	conf['user']    = 'feed_online_w'
	conf['passwd']  = '12345fEeDsTrEaM'
	conf['db']      = 'feed_online'
	conf['charset'] = 'utf8'
	return conf

# 初始化mysql连接,并返回
def init_mysql_db(conf):    #mysql_ip, mysql_user, mysql_passwd, mysql_db, mysql_port):
	db = MySQLdb.connect(host=conf['ip'], port=int(conf['port']),
	                     user=conf['user'], passwd=conf['passwd'],
	                     db=conf['db'], charset=conf['charset'])
	return db
	
#执行sql语句并返回结果
def db_execute_result(cursor, sql):
	if cursor is None or sql is None:
		return None

	try:
		cursor.execute(sql)
		data = cursor.fetchall()
		return data
	except:
		print "Error: unable to fecth data, sql=[%s]" % sql
		return None
	
# 执行sql语句并返回结果
def db_execute_commit(db, cursor, sql):
	if db is None or cursor is None or sql is None:
		return None
	
	try:
		data = cursor.execute(sql)
		db.commit()
		return data
	except:
		print "Error: unable to fecth data, sql=[%s]" % sql
		db.rollback()
		return None


def db_get_one_value(cursor, sql):
	results = db_execute_result(cursor, sql)
	return results[0][0]

def get_cover_infos(cursor, video_id):
	#infos = {}
	infos = []

	# 可变sql拼接
	fields1 = ['vc_id','vc_videoid','vc_width','vc_height', 'vc_type', 'vc_size', 'vc_isused']
	sql = 'SELECT %s FROM feed_video_cover WHERE vc_videoid="%d";' % (','.join(fields1), video_id)

	results = db_execute_result(cursor, sql)
	if results is None or len(results) == 0:
		return infos

	for row in results:
		info = {}
		for i, val in enumerate(fields1):
			info[fields1[i]] = row[i]
		#infos[row[0]] = info	# 用fileds的第一个作为key
		infos.append(info)

	return infos


# 辅助函数, flag=True表示抓取的，False表示截图的
def choose_cover_help(info, infos, flag):

	for i in infos:
		if flag != (0 == i['vc_size']):  # 用vc_size==0表示是抓取封面
			continue
		
		if 0 == len(info) or i['vc_height'] > info['vc_height']:
			info = i

	return info


# 从图片记录集中，挑选一张作为封面，然后根据挑选的封面，判断那些记录需要修改
# 返回值需要修改的图片记录数组。为[ [图片id, vc_isused字段的新值]... ]
def choose_cover(infos):
	if 0 == len(infos): return []
	
	info = {}   #infos[0]

	# 找出抓取的图片
	if 1 == len(infos):
		info = infos[0]
	else:
		info = choose_cover_help(info, infos, True)
		
	# 如果抓取图不达标，则需要比较截图
	if 0 == len(info) or info['vc_height'] < 400:
		info = choose_cover_help(info, infos, False)

	if 0 == len(info):
		msg = ' unbelieve it!!!, why still empty!!!!, %s' % infos[0]['vc_videoid']
		print msg
		logging.error(msg)
		
		return []

	
	# 计算需要修改的项
	modify_arr = []
	for i in infos:
		if i['vc_id'] == info['vc_id'] and i['vc_isused'] != 1:   modify_arr.append([i['vc_id'], 1])    # 如果当前项不是封面，则修改为1
		if i['vc_id'] != info['vc_id'] and i['vc_isused'] != 0:   modify_arr.append([i['vc_id'], 0])    # 如果当前项是封面，则修改为0
	
	msg = 'vc_videoid=%s, choose cover is =%s, update db count = %s' % \
	      (info['vc_videoid'], info['vc_id'], '[NULL]' if 0 == len(modify_arr) else str_dict_utf8(modify_arr))
	logging.info(msg)
	
	return modify_arr


def get_video_count(cursor):
	sql = 'SELECT COUNT(*) FROM feed_video_info;'
	return int(db_get_one_value(cursor, sql))
#	results = db_execute_result(cursor, sql)
#	print results[0][0]


def get_max_videoid(cursor):
	sql = 'SELECT MAX(vi_videoid) FROM feed_video_info;'
	return db_get_one_value(cursor, sql)


def get_video_ids(cursor, from_id, to_id):
	sql = 'SELECT vi_videoid FROM feed_video_info WHERE vi_videoid>=%d and vi_videoid<=%d;' % (from_id, to_id)
	results = db_execute_result(cursor, sql)
	if results is None or len(results) == 0:
		return None

	ids = [] 
	for row in results:
		ids.append(row[0])

	return ids


# 处理一条视频相关的封面。（取图片信息；挑选封面图，修改db内容）
# 返回值 >=0，成功；<0，失败
def process_one_video(db, cursor, video_id):
	infos = get_cover_infos(cursor, video_id)
	if 0 == len(infos):
		logging.error('video_id=%d, covers is NULL!' % video_id)
	
	#	for i in infos: print str_dict_utf8(i)
#	print '========================'
	modify_arr = choose_cover(infos)
	if 0 == len(modify_arr):
#		print ('video_id=%d, not need to modify db!' % video_id)
		return 0
	
	stats = [0, 0]
	for i in modify_arr:
		sql = 'UPDATE feed_video_cover SET vc_isused=%d where vc_id=%d;' % (i[1], i[0])
		ret = db_execute_commit(db, cursor, sql)
		if 1 != ret:
			stats[0] += 1
			for j in modify_arr:
				logging.error('video_id=%d, modify array=[%s]!' % (video_id, str_dict_utf8(j)))
			logging.error('==!! video_id=%d, update to db error!, sql=[%s] !!==' % (video_id, sql))
			return -1
		
	return len(modify_arr)
		
		
		
def main(from_id, to_id):
	init_log(sys.argv[0])

	db = init_mysql_db(get_mysql_config())
	cursor = db.cursor()

#	video_cnt = get_video_count(cursor)
#	video_id_max = get_max_videoid(cursor)

#	if process_one_video(db, cursor, ci) < 0: print 'process video_id =%d error!!' % ci

	# 获取视频id列表
	video_ids = get_video_ids(cursor, from_id, to_id)
	lens = len(video_ids)
	logging.info('本次处理的视频ID区间为：[%d，%d]，需要处理的记录总数为 %d' % (from_id, to_id, lens))
	
	# 初始化进度条
	stats = [0]
	bar = commtools.ProgressBar(total=lens, showtime=1)
	for i, one_id in enumerate(video_ids):
		# 每1000条刷新界面进度条
		if 0 == i % 1000:
			bar.do_process(i)
			time.sleep(0.5)

		# 做真正的处理
		if process_one_video(db, cursor, one_id) < 0:
			stats[0] += 1
			print 'process video_id =%d error!!' % one_id

	bar.do_process(lens)
	
	cursor.close()
	db.close()
	
	msg = '本次处理记录数，共 %d 条, 失败 %d 条.' % (lens, stats[0])



if __name__ == "__main__":
	argc = len(sys.argv)
	if 3 != argc and ('-v' == sys.argv[1] or '-h' == sys.argv[1]):
		print '\n\t command line is like \'python %s from_id to_id\'\n' % __file__
	else:
		from_id = int(sys.argv[1])
		to_id   = int(sys.argv[2])

		main(from_id, to_id)

# 检查数据库中的封面图，是否符合要求，根据规则选取封面图，在更新数据库
# http://192.168.5.23:7070/feed_video/info?ci=4100347805
#
#
#
